#include <iostream>
#include <cstring>
#include <vector>
#include <unistd.h>
#include <pthread.h>
#include "LockGuard.hpp"

using namespace std;

// 全局锁
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

int tickets = 1000; // 用多线程，模拟一轮抢票
#define NUM 4

class threadData // 写成类传参方便扩展
{
public:
    // threadData(int number,pthread_mutex_t *mutex)
    // {
    //     threadname="thread-"+to_string(number);
    //     lock=mutex;
    // }
    threadData(int number)
    {
        threadname = "thread-" + to_string(number);
    }

public:
    string threadname;
    pthread_mutex_t *lock;
};

void *getTicket(void *args)
{
    threadData *td = static_cast<threadData *>(args);
    const char *name = td->threadname.c_str();

    while (true)
    {
        {                               // 自动加锁解锁  用对象的生命周期控制锁
            LockGuard lockguard(&lock); // 临时的LockGuard对象
            // RAII风格的锁
            if (tickets > 0)
            {
                usleep(1000);
                printf("who=%s,get a ticket:%d\n", name, tickets);

                tickets--;
            }
            else
            {
                break;
            }
        }
        usleep(13); // 休眠一下，同一个防止一释放锁就又拿到锁了
                    // 同时，一般而言，抢票后还要执行得到票之后的后续动作，usleep模拟一下
    }
    printf("%s ... quit\n", name);
    return nullptr;
}

// void* getTicket(void* args)
// {
//     threadData*td=static_cast<threadData*>(args);
//     const char *name=td->threadname.c_str();

//     while(true)
//     {
//         //加锁  申请锁和释放锁操作是原子的
//         //线程对于锁的竞争能力可能会不同
//         //pthread_mutex_lock(td->lock);//申请锁成功，才能往后执行，不成功，阻塞等待
//         pthread_mutex_lock(&lock);
//         //临界区    所有线程串行访问
//         if(tickets>0)
//         //共享数据--数据不一致问题
//         //都在判断>0进来了，都因为自己抢到票了
//         {
//             usleep(1000);//抢票花的时间
//             printf("who=%s,get a ticket:%d\n",name,tickets);
//             //可能修改同一个票，可能自己的修改被覆盖...
//             //1.读取数据到cpu 2.计算 3.写回内存
//             tickets--;
//             //解锁
//             //pthread_mutex_unlock(td->lock);
//             pthread_mutex_unlock(&lock);
//         }
//         else
//         {
//             //解锁
//             //pthread_mutex_unlock(td->lock);
//             pthread_mutex_unlock(&lock);
//             break;
//         }
//         usleep(13);//休眠一下，同一个防止一释放锁就又拿到锁了
//                 //同时，一般而言，抢票后还要执行得到票之后的后续动作，usleep模拟一下

//     }
//     printf("%s ... quit\n",name);
//     return nullptr;
// }

int main()
{
    // //静态分配互斥量，锁
    // pthread_mutex_t lock;
    // //初始化锁
    // pthread_mutex_init(&lock,nullptr);

    vector<pthread_t> tids;            // 线程tid数组
    vector<threadData *> thread_datas; // 线程数据数组
    for (int i = 1; i <= NUM; i++)
    {
        pthread_t tid;
        // threadData*td=new threadData(i,&lock);
        threadData *td = new threadData(i);
        thread_datas.push_back(td);
        pthread_create(&tid, nullptr, getTicket, thread_datas[i - 1]);
        tids.push_back(tid);
    }

    for (auto thread : tids)
    {
        pthread_join(thread, nullptr);
    }
    for (auto td : thread_datas)
    {
        delete td;
    }

    // //销毁锁
    // pthread_mutex_destroy(&lock);
    return 0;
}